package org.property.path;

/**
 * @author Yaroslav Boichuk
 * @since 27.08.09
 * 
 *        Class extends java.util.Properties and overrides store. And has it's own method store0, which is provate in java.util.Properties and use with reflection other method of class 
 * 
 */
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Properties;

@SuppressWarnings("serial")
public class MyUtilProperties extends Properties {

	public void store(OutputStream out, String comments) throws IOException {
		store0(new BufferedWriter(new OutputStreamWriter(out, "8859_1")),
				comments, true);
	}

	// own class method, where it use method saveConvert from
	// java.util.Properties;
	private void store0(BufferedWriter bw, String comments, boolean escUnicode)
			throws IOException {

		synchronized (this) {
			for (Enumeration<?> e = keys(); e.hasMoreElements();) {
				// changed
				if (e.hasMoreElements()) {
					bw.newLine();
				}
				
				String key = (String) e.nextElement();
				String val = (String) get(key);
				key = saveConvert(key, true, escUnicode);

				val = saveConvert(val, false, escUnicode);
				bw.write(key + "=" + val);
				
			}
		}
		bw.flush();
	}

	// method return value from java.util.Properties.
	private String saveConvert(String theString, boolean escapeSpace,
			boolean escapeUnicode) {

		String returnString = null;
		try {

			Class<Properties> clazz = Properties.class;

			Constructor<Properties> c = clazz
					.getDeclaredConstructor((Class[]) null);
			c.setAccessible(true); // hack
			Properties props = c.newInstance((Object[]) null);

			Method privateMethod = clazz.getDeclaredMethod("saveConvert",
					new Class[] { String.class, boolean.class, boolean.class });

			privateMethod.setAccessible(true); // hack

			returnString = privateMethod.invoke(props, theString, escapeSpace,
					escapeUnicode).toString();

		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return returnString;

	}

}
